文章目录
  1. 1. Static Methods and Attributes
  2. 2. Constants

Static Methods and Attributes

Most methods and attributes interact with an instance of a class; static members interact with the class itself. Another way of putting it is to say that static members operate on the class-level instead of the instance-level; there is only one copy of each static member.

Here is the Book class with static attributes and methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
var Book = (function() {
// Private static attributes.
var numOfBooks = 0;
// Private static method.
function checkIsbn(isbn) {
...
}
// Return the constructor.
return function(newIsbn, newTitle, newAuthor) { // implements Publication
// Private attributes.
var isbn, title, author;
// Privileged methods.
this.getIsbn = function() {
return isbn;
};
this.setIsbn = function(newIsbn) {
if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.');
isbn = newIsbn;
};
this.getTitle = function() {
return title;
};
this.setTitle = function(newTitle) {
title = newTitle || 'No title specified';
};
this.getAuthor = function() {
return author;
};
this.setAuthor = function(newAuthor) {
author = newAuthor || 'No author specified';
};
// Constructor code.
numOfBooks++; // Keep track of how many Books have been instantiated
// with the private static attribute.
if(numOfBooks > 50) throw new Error('Book: Only 50 instances of Book can be '
+ 'created.');
this.setIsbn(newIsbn);
this.setTitle(newTitle);
this.setAuthor(newAuthor);
}
})();
// Public static method.
Book.convertToTitleCase = function(inputString) {
...
};
// Public, non-privileged methods.
Book.prototype = {
display: function() {
...
}
};

Private and privileged members are still declared within the constructor, using var and this respectively, but the constructor is changed from a normal function to a nested function that gets returned to the variable Book. This makes it possible to create a closure where you can declare private static members. The empty parentheses after the function declaration are extremely important. They serve to execute that function immediately, as soon as the code is loaded (not when the Book constructor is called).The result of that execution is another function, which is returned and set to be the Book constructor. When Book is instantiated, this inner function is what gets called; the outer function is used only to create a closure, within which you can put private static members.

In this example, the checkIsbn method is static because there is no point in creating a new
copy of it for each instance of Book. There is also a static attribute called numOfBooks, which allows you to keep track of how many times the Book constructor has been called. In this example, we use that attribute to limit the constructor to creating only 50 instances.

These private static members can be accessed from within the constructor, which means
that any private or privileged function has access to them. They have a distinct advantage over these other methods in that they are only stored in memory once. Since they are declared outside of the constructor, they do not have access to any of the private attributes, and as such, are not privileged; private methods can call private static methods, but not the other way around. A rule of thumb for deciding whether a private method should be static is to see whether it needs to access any of the instance data. If it doe not need access, making the method static is more efficient (in terms of memory use) because only a copy is ever created.

Public static members are much easier to create. They are simply created directly off of
the constructor, as with the previous method convertToTitleCase. This means you are essentially using the constructor as a namespace.

All public static methods could just as easily be declared as separate functions, but it is useful to bundle related behaviors together in one place. They are useful for tasks that are related to the class as a whole and not to any particular instance of it. They don’t directly depend on any of the data contained within the instances.

Constants

Constants are nothing more than variables that can’t be changed. In JavaScript, you can emulate constants by creating a private variable with an accessor but no mutator. Since constants are usually set at development time and don’t change with each instance that is created, it makes sense to create them as private static attributes. Here is how a call to get the constant UPPER_BOUND from Class would look:

1
Class.getUPPER_BOUND();

To implement this accessor, you would need a privileged static method, which we haven’t
covered yet. It is created just like a privileged instance method, with the this keyword:

1
2
3
4
5
6
7
8
9
10
11
12
13
var Class = (function() {
// Constants (created as private static attributes).
var UPPER_BOUND = 100;
// Privileged static method.
this.getUPPER_BOUND() {
return UPPER_BOUND;
}
...
// Return the constructor.
return function(constructorArgument) {
...
}
})();

If you have a lot of constants and don’t want to create an accessor method for each, you
can create a single generic accessor method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var Class = (function() {
// Private static attributes.
var constants = {
UPPER_BOUND: 100,
LOWER_BOUND: -100
}
// Privileged static method.
this.getConstant(name) {
return constants[name];
}
...
// Return the constructor.
return function(constructorArgument) {
...
}
})();

Then you would get a constant by calling the single accessor:

1
Class.getConstant('UPPER_BOUND');
文章目录
  1. 1. Static Methods and Attributes
  2. 2. Constants